package com.shop.filter;

import com.shop.properties.GatewayConfigProperties;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.Date;
import java.util.List;

@Component
@Slf4j
public class GlobalFilter implements org.springframework.cloud.gateway.filter.GlobalFilter, Ordered {

    /**
     * 系统参数配置
     */
    @Autowired
    private GatewayConfigProperties sysConfig;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String requestUrl = exchange.getRequest().getPath().value();
        //1、白名单放行，比如授权服务、静态资源.....
        if (checkUrls(sysConfig.getAllowUrl(), requestUrl)) {
            return chain.filter(exchange);
        }

        //2、检查token是否存在
        String token = getToken(exchange);
        if (StringUtils.isBlank(token)) {
            return invalidTokenMono(exchange);
        }

        //3 判断是否是有效的token
        try {
            //解析token
            //取出用户身份信息
            //获取用户权限
            //放入请求头中
            ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
            builder.header(HttpHeaders.DATE, String.valueOf(new Date().getTime()));

            ServerWebExchange build = exchange.mutate()
                    .request(builder.build())
                    .build();
            return chain.filter(build);
        } catch (Exception e) {
            //解析token异常，直接返回token无效
            return invalidTokenMono(exchange);
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 对url进行校验匹配
     */
    private boolean checkUrls(List<String> urls, String path) {
        AntPathMatcher pathMatcher = new AntPathMatcher();
        for (String url : urls) {
            if (pathMatcher.match(url, path))
                return true;
        }
        return false;
    }

    /**
     * 从请求头中获取Token
     */
    private String getToken(ServerWebExchange exchange) {
        String tokenStr = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        if (StringUtils.isBlank(tokenStr)) {
            return null;
        }
        String token = tokenStr.split(" ")[1];
        if (StringUtils.isBlank(token)) {
            return null;
        }
        return token;
    }

    /**
     * token不存在
     */
    private Mono<Void> invalidTokenMono(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().setLocation(URI.create(sysConfig.getRedirectUrl()));
        // 设置状态码为302（临时重定向）
        response.setStatusCode(HttpStatus.FOUND);
        return Mono.empty();
    }
}
